package com.ys.fmms.controller;

import com.ys.fmms.exception.AccountException;
import com.ys.fmms.exception.LoginException;
import com.ys.fmms.netty.MyServer;
import com.ys.fmms.pojo.LoginForm;
import com.ys.fmms.pojo.User;
import com.ys.fmms.service.UserService;
import com.ys.fmms.util.*;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;


// @Tag(name = "系统控制器")
@Api(tags = "系统控制器")
@RequestMapping("/fmms/systemController")
// @RestController
@Controller
public class SystemController {
    // @Value("${netty-port}")
    private int chatPort = 8888;

    @Resource
    private UserService userService;

    @Resource
    private RedisTemplate redisTemplate;

    @Operation(summary = "获取验证码图片")
    @GetMapping("/getVerifyCodeImage")
    @ResponseBody
    public void getVerifyCode(HttpServletResponse response) {
        // 获取验证码图片
        BufferedImage codeImage = CreateVerifyCodeImage.getverifyCodeImage();
        // 获取验证码字符串
        String verifyCode = String.valueOf(CreateVerifyCodeImage.getverifyCode());
        // 当跨域的化需要将验证码信息存储到Redis里面
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.opsForList().leftPush("code", verifyCode);
        redisTemplate.expire("code", 300, TimeUnit.SECONDS);
        // 将验证码保存到session域中 当不跨域的时候可以
        // session.setAttribute("verifyCode", verifyCode);
        try {
            ImageIO.write(codeImage, "JPEG", response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Operation(summary = "登录验证")
    @PostMapping("/login")
    @ResponseBody
    public Result login(@Parameter(description = "用户登录输入信息") @RequestBody LoginForm loginForm) {

        // 获取用户提交的验证码和session中的验证码进行比对
        String inputVerifyCode = loginForm.getVerifyCode();
        // String sessionVerifyCode = (String) session.getAttribute("verifyCode");
        List codeArr = redisTemplate.opsForList().range("code", 0, -1);
        boolean status = judgeCode(codeArr, inputVerifyCode);
        if (status) {
            return Result.build(null, ResultCodeEnum.CODE_ERROR);
        }
        // 验证码为空 或 验证码错误
        // if ("".equals(sessionVerifyCode) || !inputVerifyCode.equalsIgnoreCase(sessionVerifyCode)) {
        //     return Result.build(null, ResultCodeEnum.CODE_ERROR);
        // }
        // 验证码校验成功后移除session中的验证码
        // session.removeAttribute("verifyCode");

        Map<String, Object> map = new HashMap<>();
        // 校验用户名或密码
        String password = MD5.encrypt(loginForm.getPassword()).trim().toLowerCase();
        String username = loginForm.getUsername().trim();
        User user = userService.queryUser(password, username);
        if (user == null) {
            throw new LoginException(ResultCodeEnum.LOGIN_ERROR);
        }
        // 获取用户status 校验用户账户是否有效(0:禁用 1:正常)
        Integer userStatus = user.getStatus();
        if (userStatus == 0) {
            throw new AccountException(ResultCodeEnum.ACCOUNT_ERROR);
        }

        // 根据用户id和用户姓名生成token并返回
        String userId = user.getId();
        String userName = user.getUsername();
        String token = JwtHelper.createToken(userId, userName);
        map.put("token", token);
        return Result.ok(map);
    }

    private boolean judgeCode(List<String> codeArr, String inputVerifyCode) {
        boolean flag = false;
        Iterator<String> iterator = codeArr.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            if (!StringUtils.hasText(inputVerifyCode) || !inputVerifyCode.equalsIgnoreCase(next)) {
                flag = true;
            } else {
                break;
            }
        }
        return flag;
    }

    // 将用户头像上传到服务器的指定位置
    @Operation(summary = "上传用户头像")
    @PostMapping("/uploadAvatar")
    @ResponseBody
    public Result upload(@RequestPart("file") MultipartFile multipartFile, HttpServletRequest request) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String formatDate = sdf.format(new Date());
        String originFileName = multipartFile.getOriginalFilename();
        // 开发时存储的路径
        String fileSavePath = "d:/upload/".concat(formatDate);
        // String fileSavePath = "/home/uploadFile/".concat(formatDate);
        String newFileName = UUID.randomUUID().toString().replace("-", "").toLowerCase()
                .concat(originFileName.substring(originFileName.lastIndexOf(".")));
        File file = new File(fileSavePath);
        if (!file.isDirectory()) {
            file.mkdirs();
        }
        try {
            // 向指定的位置存储图片
            multipartFile.transferTo(new File(fileSavePath, newFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // http://localhost:9001/upload/yyyy/MM/dd/xxx.img
        String returnAvatarPath = request.getScheme() + "://" + request.getServerName() +
                ":" + request.getServerPort() + File.separator + "upload" + File.separator +
                formatDate + File.separator + newFileName;
        return Result.ok(returnAvatarPath);
    }

    @Operation(summary = "多人聊天入口")
    @RequestMapping("/groupChat")
    public String groupChat(HttpServletRequest request) {
        String uri = request.getRequestURI();
        try {
            new MyServer(chatPort, uri).run();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:/groupChat.html";
    }
}
